package com.winsdom.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.winsdom.context.BaseContext;
import com.winsdom.dto.CategoryTreeNodes;
import com.winsdom.domain.vo.BuildingResourceVO;
import com.winsdom.entity.Category;
import com.winsdom.entity.SysUser;
import com.winsdom.entity.UserProjects;
import com.winsdom.exception.BaseException;
import com.winsdom.mapper.CategoryMapper;
import com.winsdom.mapper.ReadingTaskMapper;
import com.winsdom.mapper.SysUserMapper;
import com.winsdom.mapper.UserProjectsMapper;
import com.winsdom.service.ICategoryService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.winsdom.vo.UserOrgInfoVO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.winsdom.enums.RedisKey.*;

/**
 * <p>
 * 分类表 服务实现类
 * </p>
 *
 * @author 
 * @since 2025-05-12
 */
@Slf4j
@Service
@AllArgsConstructor
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements ICategoryService {
    private final CategoryMapper categoryMapper;
    private final SysUserMapper sysUserMapper;
    private final UserProjectsMapper userProjectsMapper;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private ReadingTaskMapper readingTaskMapper;

    /**
     *根据用户名查询用户信息及组织树
     * @param username 用户名
     * @return
     */
    @Override
    public UserOrgInfoVO getUserOrgInfo(String username) {
        // 1. 查询用户基本信息
        SysUser user = sysUserMapper.selectOne(new LambdaQueryWrapper<SysUser>()
                .eq(SysUser::getUsername, username));

        if (user == null) {
            throw new BaseException("用户不存在");
        }

        if (user.getStatus() == 0){
            throw new BaseException("账号已禁用，不能管辖项目");
        }

        List<Long> categoryIds = userProjectsMapper.selectList(new LambdaQueryWrapper<UserProjects>()
                        .eq(UserProjects::getUserId, user.getId()))
                .stream()
                .map(UserProjects::getCategoryId)
                .collect(Collectors.toList());

        // 2. 查询所属组织信息
        CategoryTreeNodes orgNode = categoryMapper.getNodeById(user.getCategoryId());
        if (orgNode == null) {
            throw new BaseException("组织不存在");
        }

        // 3. 构建组织层级树
        buildSubTree(orgNode);

        // 4. 构建返回VO
        return new UserOrgInfoVO()
                .setUsername(user.getUsername())
                .setName(user.getName())
                .setOrgName(orgNode.getName())
                .setOrgTree(orgNode)
                .setOrgIds(categoryIds);
    }

    /**
     * 构建组织层级树
     * @param parentNode
     */
    private void buildSubTree(CategoryTreeNodes parentNode) {
        List<CategoryTreeNodes> children = categoryMapper.getChildrenByParentId(parentNode.getId());
        if (!children.isEmpty()) {
            parentNode.setChildren(children);
            for (CategoryTreeNodes child : children) {
                if (child.getType() <= 3) { // 只包含type<=3的节点
                    buildSubTree(child);
                }
            }
        }
    }
    //获取楼盘
    @Override
    public List<Category> getBuildings() {
        // 获取当前账号信息
        Long userId = Long.valueOf(BaseContext.getCurrentId());
        if (userId == null) {
            throw new BaseException("该账号异常");
        }
        log.info("用户id：{}", userId);
        String cacheKey = METERREADING_BUILDING.getValue() + userId;
        List<Category> categories = null;
        try {
            // 从 Redis 获取缓存数据
            categories = (List<Category>) redisTemplate.opsForValue().get(cacheKey);
        } catch (Exception e) {
            log.error("从Redis获取楼盘数据失败: {}", e.getMessage(), e);
        }
        if (categories == null) {
            try {
                // 获取当前账号对应的组织树数据
                String orgCacheKey = ORGANIZATION.getValue() + userId;
                List<CategoryTreeNodes> orgTreeNodes = null;
                try {
                    orgTreeNodes = (List<CategoryTreeNodes>) redisTemplate.opsForValue().get(orgCacheKey);
                } catch (Exception e) {
                    log.error("从Redis获取组织树数据失败: {}", e.getMessage(), e);
                }

                if (orgTreeNodes != null && !orgTreeNodes.isEmpty()) {
                    // 递归获取所有 type=3 的楼盘节点
                    Set<Long> allowedCategoryIds = new HashSet<>();


                    for (CategoryTreeNodes node : orgTreeNodes) {
                        getBuildingIdsFromTree(node, allowedCategoryIds);
                    }

                    // 根据楼盘ID集合查询对应的楼盘信息
                    if (!allowedCategoryIds.isEmpty()) {
                        LambdaQueryWrapper<Category> queryWrapper = new LambdaQueryWrapper<>();
                        queryWrapper.in(Category::getId, allowedCategoryIds)
                                .eq(Category::getType, 3);
                        categories = categoryMapper.selectList(queryWrapper);
                    }
                }
                //获取有任务的楼盘ID
                List<Long> categoryIdList = readingTaskMapper.getAllCategoryIdList();
                // 过滤掉没有任务的楼盘
                categories = categories.stream()
                        .filter(category -> categoryIdList.contains(category.getId()))
                        .collect(Collectors.toList());

                // 将查询结果存入Redis缓存
                if (categories != null) {
                    redisTemplate.opsForValue().set(cacheKey, categories, 1, TimeUnit.HOURS);
                }
            } catch (Exception e) {
                log.error("查询楼盘数据失败: {}", e.getMessage(), e);
                return null;
            }
        }
        return categories;
    }

    //递归获取组织树中的楼盘节点ID
    private void getBuildingIdsFromTree(CategoryTreeNodes node, Set<Long> allowedCategoryIds) {
        if (node.getType() == 3) {
            allowedCategoryIds.add(node.getId());
        }
        if (node.getChildren() != null) {
            for (CategoryTreeNodes child : node.getChildren()) {
                getBuildingIdsFromTree(child, allowedCategoryIds);
            }
        }
    }
    @Override
    public List<BuildingResourceVO> getBuildingResource(Long buildingId) {
        String cacheKey = METERREADING_BUILDINGRESOURCE.getValue() + buildingId;
        List<BuildingResourceVO> buildingResourceVOList = null;
        try {
            buildingResourceVOList= (List<BuildingResourceVO>) redisTemplate.opsForValue().get(cacheKey);
        }catch (Exception e) {
            log.error("从Redis获取资源数据失败: {}", e.getMessage(), e);
        }
        if(buildingResourceVOList==null) {
            try {
                buildingResourceVOList=categoryMapper.getBuildingResource(buildingId);
                if (buildingResourceVOList != null) {
                    redisTemplate.opsForValue().set(cacheKey, buildingResourceVOList, 1, TimeUnit.HOURS);
                }
            }catch (Exception e) {
                log.error("查询楼盘资源数据失败: {}", e.getMessage(), e);
                return null;
            }

        }
        return buildingResourceVOList;
    }
}
